package org.grayrabbit.cms.plugin;

import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.grayrabbit.cms.plugin.loaders.PluginLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @author sys53
 * @version 1.0
 * @created 06-一月-2012 15:47:31
 */
public class DefaultPluginManager implements PluginManager {
	 private static Logger log = LoggerFactory.getLogger(DefaultPluginManager.class);
	private final List<PluginLoader> pluginloaders;
	private final PluginStateStore store;
	private final ModuleDescriptorFactory moduleDescriptorFactory;
	private Map<String,Plugin> plugins = new HashMap<String, Plugin>();
	
	public DefaultPluginManager(PluginStateStore store, List<PluginLoader> pluginloaders,ModuleDescriptorFactory moduleDescriptorFactory){
		if(store == null){
			throw new IllegalArgumentException("PluginStateStore must bot be null.");
		}
		if(pluginloaders == null){
			throw new IllegalArgumentException("Plugin Loaders list  must bot be null.");
		}
		this.moduleDescriptorFactory = moduleDescriptorFactory;
		this.pluginloaders = pluginloaders;
		this.store = store;
	}

	/**
	 * 
	 * @param key
	 */
	public void disablePlugin(String key) {
		if (key == null) {
			throw new IllegalArgumentException("You must specify a plugin key to disable.");
		}
		if (!this.plugins.containsKey(key)) {
				log.info("No plugin was found for key {}'. Not disabling.",key);
			return;
		}
		Plugin plugin = (Plugin) this.plugins.get(key);
		notifyPluginDisabled(plugin);
		disablePluginState(plugin, getStore());
	}

	private void disablePluginState(Plugin plugin, Object store2) {
		// TODO Auto-generated method stub
		
	}

	 protected final PluginStateStore getStore()
	  {
	    return this.store;
	  }

	private void notifyPluginDisabled(Plugin plugin) {
		
	}

	/**
	 * 
	 * @param key
	 */
	public void enablePlugin(String key){
		if (key == null) {
		      throw new IllegalArgumentException("You must specify a plugin key to disable.");
		    }
		    if (!this.plugins.containsKey(key))
		    {
		        log.info("No plugin was found for key '{}'. Not enabling.",key);
		      return;
		    }
		    Plugin plugin = (Plugin)this.plugins.get(key);
		    if (!plugin.getPluginInformation().satisfiesMinJavaVersion())
		    {
		      log.error("Minimum Java version of '" + plugin.getPluginInformation().getMinJavaVersion() + "' was not satisfied for module '" + key + "'. Not enabling.");
		      return;
		    }
		    enablePluginState(plugin, getStore());
		    notifyPluginEnabled(plugin);
	}

	private void notifyPluginEnabled(Plugin plugin) {
		// TODO Auto-generated method stub
		
	}

	private void enablePluginState(Plugin plugin, Object store2) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * 
	 * @param pluginKey
	 */
	public Plugin getEnabledPlugin(String pluginKey){
		return null;
	}

	public Collection<Plugin> getEnabledPlugins(){
		return null;
	}

	/**
	 * 
	 * @param pluginKey
	 */
	public Plugin getPlugin(String pluginKey){
		return plugins.get(pluginKey);
	}

	/**
	 * 
	 * @param pluginKey
	 */
	public InputStream getPluginResourceAsStream(String pluginKey){
		return null;
	}

	public Collection<Plugin> getPlugins(){
		return plugins.values();
	}

	public void init() throws PluginParseException{
		for(PluginLoader pl : pluginloaders){
			if(pl == null)
				continue;
			for(Plugin plugin: pl.loadAllPlugins(moduleDescriptorFactory)){
				addPlugin(pl,plugin);
			}
		}
	}

	protected void addPlugin(PluginLoader pl, Plugin plugin) {
		if(this.plugins.containsKey(plugin.getKey())){
			//TODO will update plugins
		}
		this.plugins.put(plugin.getKey(), plugin);
		
	}

	/**
	 * 
	 * @param pluginJar
	 */
	public void installPlugin(PluginJar pluginJar){

	}

	/**
	 * 
	 * @param pluginKey
	 */
	public boolean isPluginEnabled(String pluginKey){
		return false;
	}

	/**
	 * 
	 * @param pluginKey
	 */
	public boolean isSystemPlugin(String pluginKey){
		return false;
	}

	public int scanForNewPlugins(){
		return 0;
	}

	/**
	 * 
	 * @param plugin
	 */
	public void uninstallPugin(Plugin plugin){

	}

	public ModuleDescriptor getPluginModule(String completeKey) {
		ModuleCompleteKey key = new ModuleCompleteKey(completeKey);
		Plugin plugin = getPlugin(key.getPluginKey());
		if (plugin == null) {
			return null;
		}
		return plugin.getModuleDescriptor(key.getModuleKey());
	}

	protected PluginManagerState getState()
	  {
	    return getStore().loadPluginState();
	  }
	
	public boolean isPluginModuleEnabled(String completeKey) {
		ModuleCompleteKey key = new ModuleCompleteKey(completeKey);
		ModuleDescriptor pluginModule = getPluginModule(completeKey);
		return (isPluginEnabled(key.getPluginKey())) && (pluginModule != null)
				&& (getState().isEnabled(pluginModule));
	}

}